﻿#region Usings

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using Microsoft.Surface.Presentation;
using ScrumTable.BL.DM.DataManagement;
using ScrumTable.Common.Collections;
using ScrumTable.UI.View.Adorners;
using ScrumTable.UI.View.Controls;
using System.Linq;
using ScrumTable.UI.View.Util;
using ScrumTable.UI.ViewModel;
using ContextMenu = ScrumTable.UI.View.WinTouch.UserControls.Menu.ContextMenu;

#endregion

namespace ScrumTable.UI.View.WinTouch.UserControls.Manager
{
    /// <summary>
    /// DropManager
    /// </summary>
    public class DropManager: IDisposable
    {

        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------
        private Dictionary<SurfaceDragCursor, Pair<IDropUserControl, Brush>> controls = new Dictionary<SurfaceDragCursor, Pair<IDropUserControl, Brush>>();
        private Dictionary<SurfaceDragCursor, ContextMenu> _contextMenus = new Dictionary<SurfaceDragCursor, ContextMenu>();

        private static Brush _canDrop;
        private static Brush _cantDrop;
        private static Brush _canDropWithoutBack;
        private static Brush _cantDropWithoutBack;

        private static Brush _warning;
        private static Brush _warningWithoutBack;

        private static Brush _saving;
        private static Brush _savingWithoutBack;

        private Window _window;
        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------
     
        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        public DropManager(Window window)
        {
            _window = window;
            SurfaceDragDrop.AddDragCanceledHandler(window, OnDrop);
            SurfaceDragDrop.AddPreviewTargetChangedHandler(window, OnTargetChanged);
            SurfaceDragDrop.AddPreviewDropHandler(window, OnDrop);
            _canDrop = GetVisual("IconDropOk", Brushes.LightGreen);
            _cantDrop = GetVisual("IconDropNok", Brushes.Red);
            _warning = GetVisual("IconDropNOkReason", Brushes.Yellow);
            _saving = GetVisual("IconDropNOkReason_Save", Brushes.LightBlue);

            _canDropWithoutBack = GetVisualWithoutBack("IconDropOk");
            _cantDropWithoutBack = GetVisualWithoutBack("IconDropNok");
            _warningWithoutBack = GetVisualWithoutBack("IconDropNOkReason");
            _savingWithoutBack = GetVisualWithoutBack("IconDropNOkReason_Save");

            

            SurfaceDragDrop.AddPreviewGiveFeedbackHandler(window, OnStartDragDrop);
        }
 
        
      

        #endregion

        #region Methods

        public void Dispose()
        {
            SurfaceDragDrop.RemoveDragCanceledHandler(_window, OnDrop);
            SurfaceDragDrop.RemovePreviewTargetChangedHandler(_window, OnTargetChanged);
            SurfaceDragDrop.RemovePreviewDropHandler(_window, OnDrop);
            SurfaceDragDrop.RemovePreviewGiveFeedbackHandler(_window, OnStartDragDrop);
        }
        
        private VisualBrush GetVisual(string iconName, SolidColorBrush iconBackColor)
        {
            VisualBrush visual = new VisualBrush();
            visual.Stretch = Stretch.UniformToFill;
            visual.AlignmentX = AlignmentX.Center;
            visual.AlignmentY = AlignmentY.Center;
            var grid = new Grid() { VerticalAlignment = VerticalAlignment.Stretch, HorizontalAlignment = HorizontalAlignment.Stretch, Background = (Brush)Application.Current.Resources["ListBoxBackgroundHorizontal"] };
            grid.Children.Add(new Label() { Background = iconBackColor, VerticalAlignment = VerticalAlignment.Stretch, HorizontalAlignment = HorizontalAlignment.Stretch, Opacity = 0.3 });
            grid.Children.Add(new Label() { Background = (Brush)Application.Current.Resources[iconName], Opacity = 0.3 });
            visual.Visual = grid;
            return visual;
        }

        private VisualBrush GetVisualWithoutBack(string iconName)
        {
            VisualBrush visual = new VisualBrush();
            visual.Stretch = Stretch.UniformToFill;
            visual.AlignmentX = AlignmentX.Center;
            visual.AlignmentY = AlignmentY.Center;
            var grid = new Grid() { VerticalAlignment = VerticalAlignment.Stretch, HorizontalAlignment = HorizontalAlignment.Stretch };
            grid.Children.Add(new Label() { Background = (Brush)Application.Current.Resources[iconName], Opacity = 0.7 });
            visual.Visual = grid;
            return visual;
        }

        private void SetBackground(FrameworkElement element, Brush brush)
        {
            element.GetType().GetProperty("Background").SetValue(element, brush, null);
        }

        private Brush GetBackground(FrameworkElement element)
        {
            return (Brush)element.GetType().GetProperty("Background").GetValue(element, null);
        }



        #endregion
        #region Events

        private void OnStartDragDrop(object sender, Microsoft.Surface.Presentation.GiveFeedbackEventArgs args)
        {
            if (_contextMenus.ContainsKey(args.Cursor) || ((AppScreen)Application.Current.MainWindow).ConfigManager.Config.IsContextMenuHide)
            {
                return;
            }
            ContextMenu menu = new ContextMenu(args.Cursor.DragSource, args.Cursor.Data);
            ((AppScreen)_window).AddItem(menu, false);
            _contextMenus[args.Cursor] = menu;
        }

       

        private void OnDrop(object a, SurfaceDragDropEventArgs b)
        {
            if(_contextMenus.ContainsKey(b.Cursor))
            {
                ((AppScreen)_window).RemoveItem(_contextMenus[b.Cursor]);
                _contextMenus.Remove(b.Cursor);
            }

            if (controls.ContainsKey(b.Cursor))
            {
                IDropUserControl dropElement = controls[b.Cursor].Left;
                if (dropElement != null)
                {
                    SetBackground(dropElement.GetRootControl, controls[b.Cursor].Right);
                }
                controls.Remove(b.Cursor);
            }

        }


        private void OnTargetChanged(object a, TargetChangedEventArgs b)
        {
            
            IDropUserControl dropElement = b.OldTarget as IDropUserControl;
            if (dropElement != null)
            {
                SetBackground(dropElement.GetRootControl, controls[b.Cursor].Right);
                controls.Remove(b.Cursor);
            }

            if (b.Cursor.CurrentTarget != null && b.Cursor.CurrentTarget is IDropUserControl)
            {
                var drop = (IDropUserControl)b.Cursor.CurrentTarget;

                Brush backColor = GetBackColor(b.Cursor, drop);

                controls[b.Cursor] = new Pair<IDropUserControl, Brush>(drop, backColor);
                CanDropResult dropResult = drop.CanDrop(b.Cursor.Data);
                if (dropResult == CanDropResult.CanDrop)
                {
                    SetBackground(drop.GetRootControl, drop.ShowIconWithbackground ? _canDrop : _canDropWithoutBack);
                }
                else
                {
                    if (dropResult == CanDropResult.WorkflowReason)
                    {
                        SetBackground(drop.GetRootControl, drop.ShowIconWithbackground ? _warning : _warningWithoutBack);
                    }
                    else if(dropResult == CanDropResult.SaveReason)
                    {
                        SetBackground(drop.GetRootControl, drop.ShowIconWithbackground ? _saving : _savingWithoutBack);
                    }
                    else
                    {
                        SetBackground(drop.GetRootControl, drop.ShowIconWithbackground ? _cantDrop : _cantDropWithoutBack);
                    }
                }
            }
        }

        private Brush GetBackColor(SurfaceDragCursor cursor, IDropUserControl drop)
        {
            Brush backColor = GetBackground(drop.GetRootControl);
            foreach (var x in controls)
            {
                if (x.Key != cursor && drop.GetRootControl == x.Value.Left)
                {
                    backColor = x.Value.Right;
                }
            }
            return backColor;
        }


        #endregion

       
    }
}
